﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using PPI.Client.Logic.XML;
using PPI.Entities.Distribution;
using PPI.Entities.XML;
using PPI.Client.Utils;
using PPI.Client.Logic.Distribution;
using PPI.Entities.Lookup;

namespace PPI.Client.Logic.Upload
{
    public class LUploadStrategyDistribution : LUploadStrategyBase
    {
        private readonly DistributionType m_distributionType;

        public LUploadStrategyDistribution(DistributionType distributionType, EXmlOutboxBase database) : base(database)
        {
            m_distributionType = distributionType;
        }

        public override void StartWork(BackgroundWorker worker, DoWorkEventArgs workerEvents)
        {
            List<EDistributionPole> lstPoles = LPole.GetDistributionPolesWithDetails(m_OutboxDatabase.ConnectionString);
            StringBuilder _errorMessage = new StringBuilder();

            Int32 _TotalToUpload = lstPoles.Count * 7;
            Int32 _CountUploaded = _TotalToUpload;

            foreach (EDistributionPole pole in lstPoles)
            {
                string message = string.Empty;

                if (LPole.CheckIsValidPole(pole, ref message))
                {
                    _errorMessage.AppendLine(message);
                }
            }

            foreach (EDistributionPole pole in lstPoles)
            {
                if (worker.CancellationPending)
                {
                    workerEvents.Cancel = true;
                    return;
                }

                if (pole.ServerID == Int32.MinValue)
                {
                   try
                    {
                        pole.DistributionType = m_distributionType;
                        pole.ServerID = LPole.Save(pole);
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LPole.UpdateUploadedData(pole, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }

                if (pole.InspectionResult.ServerId == Int32.MinValue)
                {
                    try
                    {
                        pole.InspectionResult.ServerId = LInspectionResult.Save(pole.InspectionResult, pole.ServerID);
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LPole.UpdateUploadedData(pole.InspectionResult, pole.ServerID, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }

                List<EXMissionStructures_PoleTopType> unsavedTops = new List<EXMissionStructures_PoleTopType>();
                foreach (EXMissionStructures_PoleTopType top in pole.Tops)
                {
                    if (top.ServerId == Int32.MinValue)
                        unsavedTops.Add(top);
                }

                if (unsavedTops.Count > 0) 
                {
                    List<EXMissionStructures_PoleTopType> resultSavedTops = new List<EXMissionStructures_PoleTopType>();
                    try
                    {
                        resultSavedTops = LTop.Save(unsavedTops, pole.ServerID);
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LTop.UpdateUploadedData(resultSavedTops, pole.ServerID, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }


                List<EPhase> unsavedPhases = new List<EPhase>();
                foreach (EPhase phase in pole.Phases)
                {
                    if (phase.ServerId == Int32.MinValue)
                        unsavedPhases.Add(phase);
                }

                if (unsavedPhases.Count > 0) 
                {
                    List<EPhase> resultSavedPhases = new List<EPhase>();
                    try
                    {
                        resultSavedPhases = LPhase.Save(unsavedPhases, pole.ServerID);
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LPhase.UpdateUploadedData(resultSavedPhases, pole.ServerID, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }


                List<ENote> unsavedNotes = new List<ENote>();
                foreach (ENote note in pole.Notes)
                {
                    if (note.ServerId == Int32.MinValue)
                        unsavedNotes.Add(note);
                }

                if (unsavedNotes.Count > 0) 
                {
                    List<ENote> resultSavedNotes = new List<ENote>();
                    try
                    {
                        resultSavedNotes = LNote.Save(unsavedNotes, pole.ServerID);
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LNote.UpdateUploadedData(resultSavedNotes, pole.ServerID, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }

                #region - Meters - 

                List<EMeter> unsavedMeter = new List<EMeter>();
                foreach (EMeter meter in pole.Meters)
                {
                    if (meter.ServerId == Int32.MinValue)
                        unsavedMeter.Add(meter);
                }

                if (unsavedMeter.Count > 0) 
                {
                    List<EMeter> resultSavedMeters = new List<EMeter>();
                    try
                    {
                        resultSavedMeters = LMeter.Save(unsavedMeter, pole.ServerID);

                        foreach (EMeter meter in resultSavedMeters)
                            pole.Meters.Find(delegate(EMeter m) { return m.Id == meter.Id; }).ServerId = meter.ServerId;    
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LMeter.UpdateUploadedData(resultSavedMeters, pole.ServerID, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }

                #endregion

                #region - Meters Notes -

                foreach (EMeter meter in pole.Meters)
                {
                    List<ENote> unsavedMeterNotes = new List<ENote>();
                    foreach (ENote note in meter.Notes)
                    {
                        if (note.ServerId == Int32.MinValue)
                            unsavedMeterNotes.Add(note);
                    }

                    if (unsavedMeterNotes.Count > 0) 
                    {
                        List<ENote> resultSavedMeterNotes = new List<ENote>();
                        try
                        {
                            resultSavedMeterNotes = LMeterNote.Save(unsavedMeterNotes, meter.ServerId);
                        }
                        catch (Exception ex)
                        {
                            RegisterError.SaveError(ex);
                            m_HasErrors = true;
                        }
                        finally
                        {
                            LMeterNote.UpdateUploadedData(resultSavedMeterNotes, meter.ServerId, m_OutboxDatabase.ConnectionString);
                            _CountUploaded--;
                            worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                        }
                    }
                }
                System.Threading.Thread.Sleep(100);

                _CountUploaded--;

                #endregion

                #region - Transformers -

                List<ETransformer> unsavedTransformers = new List<ETransformer>();
                foreach (ETransformer transformer in pole.Transformers)
                {
                    if (transformer.ServerId == Int32.MinValue)
                        unsavedTransformers.Add(transformer);
                }

                if (unsavedTransformers.Count > 0)
                {

                    List<ETransformer> resultSavedTransformers = new List<ETransformer>();
                    try
                    {
                        resultSavedTransformers = LTransformer.Save(unsavedTransformers, pole.ServerID);

                        foreach (ETransformer transformer in resultSavedTransformers)
                            pole.Transformers.Find(delegate(ETransformer t) { return t.Id == transformer.Id; }).ServerId = transformer.ServerId;
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LTransformer.UpdateUploadedData(resultSavedTransformers, pole.ServerID, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }
                
                #endregion

                #region - Transformer Notes -

                foreach (ETransformer transformer in pole.Transformers)
                {
                    try
                    {
                        if (transformer.Notes != null)
                            LTransformer.SaveTransformerNotes(transformer.Notes, transformer.ServerId);
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        /*LMeterNote.UpdateUploadedData(resultSavedMeterNotes, meter.ServerId,
                                                      m_OutboxDatabase.ConnectionString);*/
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                }
                #endregion

                #region - Sectionalizers -

                var unsavedSectionalizers = new List<ESectionalizer>();
                foreach (ESectionalizer sectionalizer in pole.Sectionalizers)
                {
                    if (sectionalizer.ServerId == Int32.MinValue)
                        unsavedSectionalizers.Add(sectionalizer);
                }

                if (unsavedSectionalizers.Count > 0)
                {

                    var resultSavedSectionalizers = new List<ESectionalizer>();
                    try
                    {
                        resultSavedSectionalizers = LSectionalizer.Save(unsavedSectionalizers, pole.ServerID);

                        foreach (ESectionalizer sectionalizer in resultSavedSectionalizers)
                            pole.Sectionalizers.Find(x => x.Id == sectionalizer.Id).ServerId = sectionalizer.ServerId;
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LSectionalizer.UpdateUploadedData(resultSavedSectionalizers, pole.ServerID, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }

                #endregion

                #region - Sectionalizer Notes -

                foreach (ESectionalizer sectionalizer in pole.Sectionalizers)
                {
                    try
                    {
                        if (sectionalizer.Notes != null)
                            LSectionalizer.SaveSectionalizerNotes(sectionalizer.Notes, sectionalizer.ServerId);
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        /*LMeterNote.UpdateUploadedData(resultSavedMeterNotes, meter.ServerId,
                                                      m_OutboxDatabase.ConnectionString);*/
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                }

                System.Threading.Thread.Sleep(100);

                #endregion

                #region - Reclosers -

                var unsavedReclosers = new List<ERecloser>();
                foreach (ERecloser recloser in pole.Reclosers)
                {
                    if (recloser.ServerId == Int32.MinValue)
                        unsavedReclosers.Add(recloser);
                }

                if (unsavedReclosers.Count > 0)
                {

                    var resultSavedReclosers = new List<ERecloser>();
                    try
                    {
                        resultSavedReclosers = LRecloser.Save(unsavedReclosers, pole.ServerID);

                        foreach (ERecloser recloser in resultSavedReclosers)
                            pole.Reclosers.Find(delegate(ERecloser t) { return t.Id == recloser.Id; }).ServerId = recloser.ServerId;
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        LRecloser.UpdateUploadedData(resultSavedReclosers, pole.ServerID, m_OutboxDatabase.ConnectionString);
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                    System.Threading.Thread.Sleep(100);
                }

                #endregion

                #region - Recloser Notes -

                foreach (ERecloser recloser in pole.Reclosers)
                {
                    try
                    {
                        if (recloser.Notes != null)
                            LRecloser.SaveRecloserNotes(recloser.Notes, recloser.ServerId);
                    }
                    catch (Exception ex)
                    {
                        RegisterError.SaveError(ex);
                        m_HasErrors = true;
                    }
                    finally
                    {
                        /*LMeterNote.UpdateUploadedData(resultSavedMeterNotes, meter.ServerId,
                                                      m_OutboxDatabase.ConnectionString);*/
                        _CountUploaded--;
                        worker.ReportProgress(ReportProgress(_CountUploaded, _TotalToUpload));
                    }
                }

                System.Threading.Thread.Sleep(100);

                #endregion

                if (worker.CancellationPending)
                {
                    workerEvents.Cancel = true;
                    return;
                }
            }

            worker.ReportProgress(100);
        }

        public override void FinishWork()
        {
            if (!m_HasErrors)
            {
                LXmlOutbox _serviceLogic = new LXmlOutbox(m_OutboxDatabase);

                m_OutboxDatabase.IsDataUploaded = true;
                m_OutboxDatabase.DataFinishedToUpload = DateTime.Now;
                _serviceLogic.UpdateNode(m_OutboxDatabase);
            }
        }
    }
}
